package com.yunkazaixian.syntelecom.utils;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.StandardCharsets;
import java.util.concurrent.TimeUnit;


public class NettyClient {
    private final Logger log = LoggerFactory.getLogger(NettyClient.class);
    public static Channel channel;
    private Bootstrap bootstrap;
    private EventLoopGroup group;
    private String serverIP = "115.233.219.190";
    private int serverPort = 2903;

    public void start(int port) throws Exception {
        // 创建一个工作线程组
        group = new NioEventLoopGroup();
        try {
            bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {

                            //FixedLengthFrameDecoder添加到pipeline中，用来处理粘包问题

                            ByteBuf delimiter = Unpooled.copiedBuffer("$$".getBytes());
                            ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter));
                            ch.pipeline().addLast(new StringDecoder(StandardCharsets.UTF_8));
                            ch.pipeline().addLast(new StringEncoder(StandardCharsets.UTF_8));
                            ch.pipeline().addLast(new ClientHandler(NettyClient.this));
                        }
                    });

            // 连接到服务器，并同步等待连接完成
            ChannelFuture f = bootstrap.connect(serverIP, serverPort).sync();
            if (f.isSuccess()) {
                //如果连接服务器成功，那么将channel保存起来，便于定时任务调用
                channel = f.channel();
            }
        } catch (Exception e) {
            e.printStackTrace();
            connect();
        }
    }

    public void connect() throws Exception {
        ChannelFuture cf = bootstrap.connect(serverIP, serverPort);
        cf.addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (future.isSuccess()) {
                    channel = future.channel();
                    log.error("重连服务端成功");
                } else {
                    future.channel().eventLoop().schedule(() -> {
                        log.error("重新连接服务端...");
                        try {
                            connect();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }, 10, TimeUnit.SECONDS);
                }
            }
        });
        //对通道关闭进行监听
        cf.channel().closeFuture().sync();
    }


    public void push(Object o) {
        if (channel == null) {
            //netty没有成功建立连接
            System.out.println("netty没有成功建立连接");
            return;
        }
        //todo 此处是您自己的业务逻辑，计算出来请求参数中所需要的数据，发送到netty
        String pushString=FastJsonUtils.toJson(o);
        System.out.println("推送内容："+pushString);
        channel.writeAndFlush(pushString + "$$");//数据的最后一定要加上"$$"分隔符，因为会出现粘包问题，服务端需要进行拆包

    }
}